﻿using Als.Common.String;
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Web;

namespace Als.Common.Net
{
    public static class IpHelper
    {
        #region 获取客户端IP

        /// <summary>
        /// 获取客户端IP
        /// </summary>
        /// <returns></returns>
        public static string GetVisitorIp()
        {
            var result = "";
            try
            {
                result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                //可能有代理 
                if (!string.IsNullOrWhiteSpace(result))
                {
                    //没有"." 肯定是非IP格式
                    if (result.IndexOf(".", System.StringComparison.Ordinal) == -1)
                        result = "";
                    else
                    {
                        //有","，估计多个代理。取第一个不是内网的IP。
                        if (result.IndexOf(",", System.StringComparison.Ordinal) != -1)
                        {
                            result = result.Replace(" ", string.Empty).Replace("\"", string.Empty);
                            var temparyip = result.Split(",;".ToCharArray());
                            if (temparyip.Length > 0)
                            {
                                foreach (var t in temparyip.Where(t => t.IsValidIp()
                                        && t.Substring(0, 3) != "10."
                                        && t.Substring(0, 7) != "192.168"
                                        && t.Substring(0, 7) != "172.16."))
                                {
                                    return t == "::1" ? "127.0.0.1" : t;
                                }
                            }
                        }
                        //代理即是IP格式
                        else if (result.IsValidIp())
                            return result == "::1" ? "127.0.0.1" : result;
                        //代理中的内容非IP
                        else
                            result = "";
                    }
                }
                if (string.IsNullOrWhiteSpace(result))
                    result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                if (string.IsNullOrWhiteSpace(result))
                    result = HttpContext.Current.Request.UserHostAddress;
                return result == "::1" ? "127.0.0.1" : result;
            }
            catch (Exception)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(result))
                        result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                    if (string.IsNullOrWhiteSpace(result))
                        result = HttpContext.Current.Request.UserHostAddress;
                    return result == "::1" ? "127.0.0.1" : result;
                }
                catch (Exception ex)
                {
                    return "获取IP失败:" + ex.Message;
                }
            }
        }

        #endregion

        #region 获得用户IP
        /// <summary>
        /// 获得用户IP
        /// </summary>
        public static string GetUserIp()
        {
            var isErr = false;
            var ip = HttpContext.Current.Request.ServerVariables["HTTP_X_ForWARDED_For"] == null ? HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] : HttpContext.Current.Request.ServerVariables["HTTP_X_ForWARDED_For"];
            if (ip.Length > 15)
                isErr = true;
            else
            {
                var temp = ip.Split('.');
                if (temp.Length == 4)
                {
                    foreach (var t in temp)
                    {
                        if (t.Length > 3) isErr = true;
                    }
                }
                else
                    isErr = true;
            }
            return isErr ? "1.1.1.1" : ip;
        }
        #endregion

        #region 获取本机的局域网IP
        /// <summary>
        /// 获取本机的局域网IP
        /// </summary>        
        public static string Lanip
        {
            get
            {
                //获取本机的IP列表,IP列表中的第一项是局域网IP，第二项是广域网IP
                var addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
                //如果本机IP列表为空，则返回空字符串
                return addressList.Length < 1 ? "" : addressList[0].ToString();
                //返回本机的局域网IP
            }
        }
        #endregion

        #region 获取本机在Internet网络的广域网IP
        /// <summary>
        /// 获取本机在Internet网络的广域网IP
        /// </summary>        
        public static string Wanip
        {
            get
            {
                //获取本机的IP列表,IP列表中的第一项是局域网IP，第二项是广域网IP
                var addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
                //如果本机IP列表小于2，则返回空字符串
                return addressList.Length < 2 ? "" : addressList[1].ToString();
                //返回本机的广域网IP
            }
        }
        #endregion

        #region 将字符串形式的IP地址转换成IPAddress对象
        /// <summary>
        /// 将字符串形式的IP地址转换成IPAddress对象
        /// </summary>
        /// <param name="ip">字符串形式的IP地址</param>        
        public static IPAddress StringToIpAddress(string ip)
        {
            return IPAddress.Parse(ip);
        }
        #endregion

        #region 检查端口号是否正确，返回正确的端口号
        /// <summary>
        /// 检查设置的端口号是否正确，并返回正确的端口号,无效端口号返回-1。
        /// </summary>
        /// <param name="port">设置的端口号</param>        
        public static int GetValidPort(string port)
        {
            //声明返回的正确端口号
            var validPort = -1;
            //最小有效端口号
            const int minport = 0;
            //最大有效端口号
            const int maxport = 65535;
            //检测端口号
            try
            {
                //传入的端口号为空则抛出异常
                if (port == "")
                {
                    throw new Exception("端口号不能为空！");
                }

                //检测端口范围
                if ((Convert.ToInt32(port) < minport) || (Convert.ToInt32(port) > maxport))
                {
                    throw new Exception("端口号范围无效！");
                }

                //为端口号赋值
                validPort = Convert.ToInt32(port);
            }
            catch (Exception)
            {
                // ignored
            }

            return validPort;
        }
        #endregion

        #region 创建一个IPEndPoint对象
        /// <summary>
        /// 创建一个IPEndPoint对象
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <param name="port">端口号</param>        
        public static IPEndPoint CreateIpEndPoint(string ip, int port)
        {
            var ipAddress = StringToIpAddress(ip);
            return new IPEndPoint(ipAddress, port);
        }
        #endregion

        #region 创建一个TcpListener对象
        /// <summary>
        /// 创建一个自动分配IP和端口的TcpListener对象
        /// </summary>        
        public static TcpListener CreateTcpListener()
        {
            //创建一个自动分配的网络节点
            var ipAddress = IPAddress.Any;
            var localEndPoint = new IPEndPoint(ipAddress, 0);
            return new TcpListener(localEndPoint);
        }

        /// <summary>
        /// 创建一个TcpListener对象
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <param name="port">端口</param>        
        public static TcpListener CreateTcpListener(string ip, int port)
        {
            //创建一个网络节点
            var ipAddress = StringToIpAddress(ip);
            var localEndPoint = new IPEndPoint(ipAddress, port);
            return new TcpListener(localEndPoint);
        }

        #endregion

        #region 创建一个基于TCP协议的Socket对象
        /// <summary>
        /// 创建一个基于TCP协议的Socket对象
        /// </summary>        
        public static Socket CreateTcpSocket()
        {
            return new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        #endregion

        #region 创建一个基于UDP协议的Socket对象
        /// <summary>
        /// 创建一个基于UDP协议的Socket对象
        /// </summary>        
        public static Socket CreateUdpSocket()
        {
            return new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        }
        #endregion





    }
}
